bitkeeper revision 1.269 (3f05631fUbZceaMD9jXHZuX-gUlgYw)
authorrac61@labyrinth.cl.cam.ac.uk <rac61@labyrinth.cl.cam.ac.uk>
Fri, 4 Jul 2003 11:21:03 +0000 (11:21 +0000)
committerrac61@labyrinth.cl.cam.ac.uk <rac61@labyrinth.cl.cam.ac.uk>
Fri, 4 Jul 2003 11:21:03 +0000 (11:21 +0000)
Start refactoring VD stuff into new package structure
Implemented physical disk access stuff for sos22's shiny new interface for same

18 files changed:
.rootkeys
tools/control/src/org/xenoserver/cmdline/Main.java
tools/control/src/org/xenoserver/cmdline/ParseGroup.java
tools/control/src/org/xenoserver/cmdline/ParsePartitionsList.java [new file with mode: 0644]
tools/control/src/org/xenoserver/cmdline/ParsePhysicalGrant.java [new file with mode: 0644]
tools/control/src/org/xenoserver/cmdline/ParsePhysicalList.java [new file with mode: 0644]
tools/control/src/org/xenoserver/cmdline/ParsePhysicalRevoke.java [new file with mode: 0644]
tools/control/src/org/xenoserver/control/CommandPhysicalGrant.java [new file with mode: 0644]
tools/control/src/org/xenoserver/control/CommandPhysicalList.java [new file with mode: 0644]
tools/control/src/org/xenoserver/control/CommandPhysicalRevoke.java [new file with mode: 0644]
tools/control/src/org/xenoserver/control/Extent.java [new file with mode: 0644]
tools/control/src/org/xenoserver/control/Library.java [new file with mode: 0644]
tools/control/src/org/xenoserver/control/Mode.java [new file with mode: 0644]
tools/control/src/org/xenoserver/control/Partition.java [new file with mode: 0644]
tools/control/src/org/xenoserver/control/PartitionManager.java [new file with mode: 0644]
tools/control/src/org/xenoserver/control/Settings.java
tools/control/src/org/xenoserver/control/XML.java [new file with mode: 0644]
tools/control/src/org/xenoserver/control/XMLHelper.java [new file with mode: 0644]

index f88f1482ca0c85eba582421365afe2ef476e5ec0..c98ff9fa0f3b5b213ee4276970df94ada9a8a254 100644 (file)
--- a/.rootkeys
+++ b/.rootkeys
 3f042c35UhRkvblwKSx0KW2QHUn3Fw tools/control/src/org/xenoserver/cmdline/ParseFailedException.java
 3f0445524oTSyogDGmCAyKMM665Rxg tools/control/src/org/xenoserver/cmdline/ParseGroup.java
 3f042c35Inw0LzkOzXo9ncbEHZzUHA tools/control/src/org/xenoserver/cmdline/ParseHelp.java
+3f05631djnPcaqmzMFSa8RLmGCZ-0Q tools/control/src/org/xenoserver/cmdline/ParsePartitionsList.java
+3f05631dswxJX_TpcuG6tBstyHSetg tools/control/src/org/xenoserver/cmdline/ParsePhysicalGrant.java
+3f05631dMY7PMkwSY7zBFelGJ8goVg tools/control/src/org/xenoserver/cmdline/ParsePhysicalList.java
+3f05631dYDFXv6mwNFAgz3ta9kShJA tools/control/src/org/xenoserver/cmdline/ParsePhysicalRevoke.java
 3f042c35V-Bf3dlIe1r5mZs8ZTPSvA tools/control/src/org/xenoserver/control/Command.java
 3f042c35U_4O2eovLKUgo2avPPHKUw tools/control/src/org/xenoserver/control/CommandDomainDestroy.java
 3f042c3570VRwuzl94tEozOIVBycNg tools/control/src/org/xenoserver/control/CommandDomainList.java
 3f042c36GqoXJJj_BvWGwBeKwEzgvg tools/control/src/org/xenoserver/control/CommandDomainStart.java
 3f042c36bmZJD0xrxURD075avUlIUg tools/control/src/org/xenoserver/control/CommandDomainStop.java
 3f042c35hdwL__Airzyz4HutOgGRqQ tools/control/src/org/xenoserver/control/CommandFailedException.java
+3f05631ev3UK5FRi5vgR08zDp3OZYw tools/control/src/org/xenoserver/control/CommandPhysicalGrant.java
+3f05631e_G6wzHhEnpihX0pIkEsbMw tools/control/src/org/xenoserver/control/CommandPhysicalList.java
+3f05631eGWxq7bojQbMa-tGxsENIhw tools/control/src/org/xenoserver/control/CommandPhysicalRevoke.java
 3eb781fdBRXfSlWzK6GXlIQIlHFoaQ tools/control/src/org/xenoserver/control/Defaults.java
 3ec41f7cQ7Ug739JBDrsVH-7KJ5MvQ tools/control/src/org/xenoserver/control/Domain.java
+3ec41f7cAzdBu0lkuTTQx92rqSM9Qw tools/control/src/org/xenoserver/control/Extent.java
 3eb781fdDeZEopemXIVg_ARCGKSmBw tools/control/src/org/xenoserver/control/InetAddressPattern.java
+3ec41f7cqN_uVR_7TqjgypDfFdGyrg tools/control/src/org/xenoserver/control/Library.java
+3ec41f7dsb1R8BvBNzjYufMrx6ONdA tools/control/src/org/xenoserver/control/Mode.java
+3ec41f7dbqJLTy1msByMzQhy3jHHyQ tools/control/src/org/xenoserver/control/Partition.java
+3ec41f7djIGkw6M9meq8-YZ1WDATcw tools/control/src/org/xenoserver/control/PartitionManager.java
 3eb781fdmMkFbyb2SAGR0vsuFtl9Lw tools/control/src/org/xenoserver/control/Settings.java
 3eb781fdpgi83RpUvQWVccWjsDJK7w tools/control/src/org/xenoserver/control/StringPattern.java
+3ec41f7dUPpYTwYL5QVpRBv6PLKPrg tools/control/src/org/xenoserver/control/XML.java
+3ec41f7d7Try-2zmfnpaALwJjY0GCA tools/control/src/org/xenoserver/control/XMLHelper.java
 3ec41f7csVaMDEEUMZBotpSftCy0rg tools/control/src/uk/ac/cam/cl/xeno/xenctl/Extent.java
 3ec41f7cO5uUI4qZmJ29jsammoZP4Q tools/control/src/uk/ac/cam/cl/xeno/xenctl/Library.java
 3ec41f7civcv4mQiYK0DeX9Zvsxhrw tools/control/src/uk/ac/cam/cl/xeno/xenctl/Main.java.orig
index b21aba57b311b101114cc3541d2a40e031140819..624a07c951657799afb1780ee12dcae3606e7756 100644 (file)
@@ -17,9 +17,19 @@ public class Main {
       new ParseDomainDestroy(),
       new ParseDomainList()
     };
+  static final CommandParser partitioncommands[] =
+    { new ParsePartitionsList()
+    };
+  static final CommandParser physicalcommands[] =
+    { new ParsePhysicalGrant(),
+      new ParsePhysicalRevoke(),
+      new ParsePhysicalList()
+    };
   static final CommandParser commands[] =
     { help,
-      new ParseGroup( "domain", domaincommands )
+      new ParseGroup( "domain", domaincommands ),
+      new ParseGroup( "partitions", partitioncommands ),
+      new ParseGroup( "physical", physicalcommands )
     };
   static final CommandParser parser = new ParseGroup( null, commands );
 
index 1903dc4b2d4cab95df0970f2b6f7d5fdcbb47cff..02ef3743d3dfbfa172d9e8abe8e5408f7799d228 100644 (file)
@@ -26,7 +26,7 @@ public class ParseGroup extends CommandParser {
     String c = (String) args.removeFirst();
     for (i = 0; i < commands.length; i++) {
       if (commands[i].getName().equals(c)) {
-        if (getFlagParameter(args, '?')) {
+        if (!args.isEmpty() && args.getFirst().equals("-?")) {
           commands[i].printHelpText(null);
         } else {
           commands[i].parse(d, args);
@@ -44,12 +44,10 @@ public class ParseGroup extends CommandParser {
   }
 
   public String getUsage() {
-    // TODO Auto-generated method stub
     return null;
   }
 
   public String getHelpText() {
-    // TODO Auto-generated method stub
     return null;
   }
 
diff --git a/tools/control/src/org/xenoserver/cmdline/ParsePartitionsList.java b/tools/control/src/org/xenoserver/cmdline/ParsePartitionsList.java
new file mode 100644 (file)
index 0000000..02a754f
--- /dev/null
@@ -0,0 +1,57 @@
+package org.xenoserver.cmdline;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+
+import org.xenoserver.control.CommandFailedException;
+import org.xenoserver.control.Defaults;
+import org.xenoserver.control.Library;
+import org.xenoserver.control.Partition;
+import org.xenoserver.control.PartitionManager;
+import org.xenoserver.control.Settings;
+import org.xenoserver.control.XML;
+
+public class ParsePartitionsList extends CommandParser {
+
+  public void parse(Defaults d, LinkedList args) throws ParseFailedException, CommandFailedException {
+    XML.load_state( PartitionManager.it, Settings.STATE_INPUT_FILE );
+    Iterator i = PartitionManager.it.iterator();
+    int idx = 1;
+    System.out.println( "     maj:min " + "    blocks " + "start sect " +
+                        " num sects " + "name" );
+    while (i.hasNext()) {
+      Partition p = (Partition) i.next();
+
+      if (p.getIsXeno()) {
+        System.out.print("[ ");
+      } else {
+        System.out.print("  ");
+      }
+      System.out.print(Library.format(idx++, 2, 0) + " ");
+      System.out.print(Library.format(p.getMajor(),3,0) + ":" + 
+          Library.format(p.getMinor(),3,1) + " " +
+          Library.format(p.getBlocks(),10,0) + " " +
+          Library.format(p.getStartSect(),10,0) + " " +
+          Library.format(p.getNumSects(),10,0) + " " +
+          Library.format(p.getName(),7,1));   
+      if (p.getIsXeno()) {
+        System.out.println("]");
+      } else {
+        System.out.println();
+      }
+    }
+  }
+
+  public String getName() {
+    return "list";
+  }
+
+  public String getUsage() {
+    return "";
+  }
+
+  public String getHelpText() {
+    return "List real partition information";
+  }
+
+}
diff --git a/tools/control/src/org/xenoserver/cmdline/ParsePhysicalGrant.java b/tools/control/src/org/xenoserver/cmdline/ParsePhysicalGrant.java
new file mode 100644 (file)
index 0000000..6792a43
--- /dev/null
@@ -0,0 +1,65 @@
+package org.xenoserver.cmdline;
+
+import java.util.LinkedList;
+
+import org.xenoserver.control.CommandFailedException;
+import org.xenoserver.control.CommandPhysicalGrant;
+import org.xenoserver.control.Defaults;
+import org.xenoserver.control.Extent;
+import org.xenoserver.control.Mode;
+import org.xenoserver.control.Partition;
+import org.xenoserver.control.PartitionManager;
+import org.xenoserver.control.Settings;
+import org.xenoserver.control.XML;
+
+public class ParsePhysicalGrant extends CommandParser {
+  public void parse(Defaults d, LinkedList args) throws ParseFailedException, CommandFailedException {
+    int domain_id = getIntParameter(args, 'n', 0);
+    boolean force = getFlagParameter(args, 'f');
+    String partition_name = getStringParameter(args, 'p', "");
+    boolean write = getFlagParameter(args, 'w');
+    
+    if (domain_id == 0)
+      throw new ParseFailedException("Expected -n<domain_id>");
+    if (partition_name.equals(""))
+      throw new ParseFailedException("Expected -p<partition_name>");
+      
+    Mode mode;
+    if (write)
+      mode = Mode.READ_WRITE;
+    else
+      mode = Mode.READ_ONLY;
+      
+    // Initialise the partition manager and look up the partition
+    XML.load_state( PartitionManager.it, Settings.STATE_INPUT_FILE );
+    Partition p = PartitionManager.it.get_partition(partition_name);
+    
+    if ( p == null )
+      throw new CommandFailedException("Partition " + partition_name + " does not exist.");
+    
+    // Check if this partition belongs to the VDM
+    if (p.getIsXeno() && !force)
+      throw new CommandFailedException("Refusing to grant physical access as the given partition is allocated to the virtual disk manager. Use -f if you are sure.");
+     
+    // Convert the partition into a physical extent
+    Extent e = p.toExtent();
+    
+    String output = new CommandPhysicalGrant( d, domain_id, e, mode ).execute();
+    if ( output != null )
+      System.out.println( output );
+  }
+
+  public String getName() {
+    return "grant";
+  }
+
+  public String getUsage() {
+    return "[-f] [-w] [-n<domain_id>] [-p<partition_name>]";
+  }
+
+  public String getHelpText() {
+    return "Grant the specified domain access to the given partition.  -w grants" +
+           " read-write instead of read-only.  -f forcibly grants access.";
+  }
+
+}
diff --git a/tools/control/src/org/xenoserver/cmdline/ParsePhysicalList.java b/tools/control/src/org/xenoserver/cmdline/ParsePhysicalList.java
new file mode 100644 (file)
index 0000000..c08a881
--- /dev/null
@@ -0,0 +1,74 @@
+package org.xenoserver.cmdline;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Map.Entry;
+
+import org.xenoserver.control.CommandFailedException;
+import org.xenoserver.control.CommandPhysicalList;
+import org.xenoserver.control.Defaults;
+import org.xenoserver.control.Extent;
+import org.xenoserver.control.Library;
+import org.xenoserver.control.Mode;
+import org.xenoserver.control.Partition;
+import org.xenoserver.control.PartitionManager;
+import org.xenoserver.control.Settings;
+import org.xenoserver.control.XML;
+
+public class ParsePhysicalList extends CommandParser {
+
+  public void parse(Defaults d, LinkedList args) throws ParseFailedException, CommandFailedException {
+    int domain_id = getIntParameter(args, 'n', 0);
+    if (domain_id == 0)
+      throw new ParseFailedException("Expected -n<domain_id>");
+
+    // Initialise the partition manager
+    XML.load_state( PartitionManager.it, Settings.STATE_INPUT_FILE );
+    
+    CommandPhysicalList list = new CommandPhysicalList( d, domain_id );
+    String output = list.execute();
+    if ( output != null )
+      System.out.println( output );
+      
+    System.out.println( "maj:min " + "    blocks " + "start sect " +
+                        " num sects " + "name    " + "access" );
+    Iterator i = list.extents().entrySet().iterator();
+    while ( i.hasNext() )
+    {
+      Entry entry = (Entry) i.next(); 
+      Extent e = (Extent) entry.getKey();
+      String mode = entry.getValue().toString();
+      Partition p = PartitionManager.it.get_partition( e );
+      if ( p != null ) {
+        System.out.println(Library.format(p.getMajor(),3,0) + ":" + 
+          Library.format(p.getMinor(),3,1) + " " +
+          Library.format(p.getBlocks(),10,0) + " " +
+          Library.format(p.getStartSect(),10,0) + " " +
+          Library.format(p.getNumSects(),10,0) + " " +
+          Library.format(p.getName(),7,1) + " " +
+          Library.format(mode,2,1));   
+      } else {
+        System.out.println(Library.format(e.getMajor(),3,0) + ":" +
+          Library.format(e.getMinor(),3,1) + " " +
+          "          " + " " +
+          Library.format(e.getOffset(),10,0) + " " +
+          Library.format(e.getSize(),10,0) + " " +
+          "       " + " " +
+          Library.format(mode,2,1));
+      }
+    }
+  }
+
+  public String getName() {
+    return "list";
+  }
+
+  public String getUsage() {
+    return "[-n<domain_id>]";
+  }
+
+  public String getHelpText() {
+    return "List all physical access which the given domain has been granted.";
+  }
+
+}
diff --git a/tools/control/src/org/xenoserver/cmdline/ParsePhysicalRevoke.java b/tools/control/src/org/xenoserver/cmdline/ParsePhysicalRevoke.java
new file mode 100644 (file)
index 0000000..8527845
--- /dev/null
@@ -0,0 +1,51 @@
+package org.xenoserver.cmdline;
+
+import java.util.LinkedList;
+
+import org.xenoserver.control.CommandFailedException;
+import org.xenoserver.control.CommandPhysicalRevoke;
+import org.xenoserver.control.Defaults;
+import org.xenoserver.control.Extent;
+import org.xenoserver.control.Partition;
+import org.xenoserver.control.PartitionManager;
+import org.xenoserver.control.Settings;
+import org.xenoserver.control.XML;
+
+public class ParsePhysicalRevoke extends CommandParser {
+  public void parse(Defaults d, LinkedList args) throws ParseFailedException, CommandFailedException {
+    int domain_id = getIntParameter(args, 'n', 0);
+    String partition_name = getStringParameter(args, 'p', "");
+    
+    if (domain_id == 0)
+      throw new ParseFailedException("Expected -n<domain_id>");
+    if (partition_name.equals(""))
+      throw new ParseFailedException("Expected -p<partition_name>");
+      
+    // Initialise the partition manager and look up the partition
+    XML.load_state( PartitionManager.it, Settings.STATE_INPUT_FILE );
+    Partition p = PartitionManager.it.get_partition(partition_name);
+    
+    if ( p == null )
+      throw new CommandFailedException("Partition " + partition_name + " does not exist.");
+
+    // Convert the partition into a physical extent
+    Extent e = p.toExtent();
+    
+    String output = new CommandPhysicalRevoke( d, domain_id, e ).execute();
+    if ( output != null )
+      System.out.println( output );
+  }
+
+  public String getName() {
+    return "revoke";
+  }
+
+  public String getUsage() {
+    return "[-n<domain_id>] [-p<partition_name>]";
+  }
+
+  public String getHelpText() {
+    return "Revoke access to the given partition from the specified domain.";
+  }
+
+}
diff --git a/tools/control/src/org/xenoserver/control/CommandPhysicalGrant.java b/tools/control/src/org/xenoserver/control/CommandPhysicalGrant.java
new file mode 100644 (file)
index 0000000..c7152e4
--- /dev/null
@@ -0,0 +1,66 @@
+package org.xenoserver.control;
+
+public class CommandPhysicalGrant extends Command {
+  private Defaults d;
+  private int domain_id;
+  private Extent extent;
+  private Mode mode;
+
+  /**
+   * Constructor for CommandPhysicalGrant.
+   * @param d Defaults object to use.
+   * @param domain_id Domain to grant access for.
+   * @param extent Extent to grant access to.
+   * @param mode Access mode to grant.
+   */
+  public CommandPhysicalGrant(
+    Defaults d,
+    int domain_id,
+    Extent extent,
+    Mode mode) {
+    this.d = d;
+    this.domain_id = domain_id;
+    this.extent = extent;
+    this.mode = mode;
+  }
+
+  public String execute() throws CommandFailedException {
+    Runtime r = Runtime.getRuntime();
+    String output = null;
+
+    try {
+      Process start_p;
+      String start_cmdarray[] = new String[6];
+      int start_rc;
+      start_cmdarray[0] = d.XIToolsDir + "xi_phys_grant";
+      if ( mode == Mode.READ_WRITE )
+        start_cmdarray[1] = "rw";
+      else if ( mode == Mode.READ_ONLY )
+        start_cmdarray[1] = "ro";
+      else
+        throw new CommandFailedException( "Unknown access mode '" + mode + "'" );
+      start_cmdarray[2] = Integer.toString( domain_id );
+      start_cmdarray[3] = Short.toString( extent.getDisk() );
+      start_cmdarray[4] = Long.toString( extent.getOffset() );
+      start_cmdarray[5] = Long.toString( extent.getSize() );
+
+      if (Settings.TEST) {
+        output = reportCommand(start_cmdarray);
+      } else {
+        start_p = r.exec(start_cmdarray);
+        start_rc = start_p.waitFor();
+        if (start_rc != 0) {
+          throw CommandFailedException.XICommandFailed("Could not grant physical access", start_cmdarray);
+        }
+        output = "Granted physical access to domain " + domain_id;
+      }
+    } catch (CommandFailedException e) {
+      throw e;
+    } catch (Exception e) {
+      throw new CommandFailedException("Could not grant physical access (" + e + ")", e);
+    }
+
+    return output;
+  }
+
+}
diff --git a/tools/control/src/org/xenoserver/control/CommandPhysicalList.java b/tools/control/src/org/xenoserver/control/CommandPhysicalList.java
new file mode 100644 (file)
index 0000000..03bed9e
--- /dev/null
@@ -0,0 +1,98 @@
+package org.xenoserver.control;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+/**
+ * Lists details of all extents the given domain has access to.
+ * After execute() has been called, call extents() to get the map of extents
+ * to modes.
+ */
+public class CommandPhysicalList extends Command {
+  private int domain_id;
+  private Defaults d;
+  private Map map = new HashMap();
+
+  /**
+   * Constructor for CommandDomainList.
+   * @param d Defaults object to use.
+   */
+  public CommandPhysicalList(Defaults d, int domain_id) {
+    this.d = d;
+    this.domain_id = domain_id;
+  }
+
+  /**
+   * Retrieves the list of extents.
+   * @return null, call extents() to get the list.
+   */
+  public String execute() throws CommandFailedException {
+    Runtime r = Runtime.getRuntime();
+    int rc = 0;
+    String outline;
+    BufferedReader in;
+    String output = null;
+
+    try {
+      Process start_p;
+      String start_cmdarray[] = new String[2];
+      int start_rc;
+      start_cmdarray[0] = d.XIToolsDir + "xi_phys_probe";
+      start_cmdarray[1] = Integer.toString( domain_id );
+
+      if (Settings.TEST) {
+        output = reportCommand(start_cmdarray);
+      } else {
+        start_p = r.exec(start_cmdarray);
+        start_rc = start_p.waitFor();
+        if (start_rc != 0) {
+          throw CommandFailedException.XICommandFailed("Could not get extent list", start_cmdarray);
+        }
+
+        in =
+          new BufferedReader(new InputStreamReader(start_p.getInputStream()));
+
+        outline = in.readLine();
+        while (outline != null) {
+          Extent extent = new Extent();
+
+          StringTokenizer st = new StringTokenizer(outline);
+          if (st.hasMoreTokens()) {
+            extent.disk = Short.parseShort(st.nextToken(),16);
+          }
+          if (st.hasMoreTokens()) {
+            extent.offset = Long.parseLong(st.nextToken(),16);
+          }
+          if (st.hasMoreTokens()) {
+            extent.size = Long.parseLong(st.nextToken(),16);
+          }
+          if (st.hasMoreTokens()) {
+            String mode = st.nextToken();
+            if ( mode.equals( "rw" ) )
+              map.put( extent, Mode.READ_WRITE );
+            else if ( mode.equals ( "r" ) )
+              map.put( extent, Mode.READ_ONLY );
+            else
+              throw new CommandFailedException("Could not parse access mode " + mode);
+          }
+
+          outline = in.readLine();
+        }
+
+      }
+    } catch (CommandFailedException e) {
+      throw e;
+    } catch (Exception e) {
+      throw new CommandFailedException("Could not get extent list(" + e + ")", e);
+    }
+
+    return output;
+  }
+  
+  public Map extents() {
+    return map;
+  }
+}
diff --git a/tools/control/src/org/xenoserver/control/CommandPhysicalRevoke.java b/tools/control/src/org/xenoserver/control/CommandPhysicalRevoke.java
new file mode 100644 (file)
index 0000000..63052b1
--- /dev/null
@@ -0,0 +1,56 @@
+package org.xenoserver.control;
+
+public class CommandPhysicalRevoke extends Command {
+  private Defaults d;
+  private int domain_id;
+  private Extent extent;
+
+  /**
+   * Constructor for CommandPhysicalRevoke.
+   * @param d Defaults object to use.
+   * @param domain_id Domain to revoke access from.
+   * @param extent Extent to revoke access from.
+   */
+  public CommandPhysicalRevoke(
+    Defaults d,
+    int domain_id,
+    Extent extent) {
+    this.d = d;
+    this.domain_id = domain_id;
+    this.extent = extent;
+  }
+
+  public String execute() throws CommandFailedException {
+    Runtime r = Runtime.getRuntime();
+    String output = null;
+
+    try {
+      Process start_p;
+      String start_cmdarray[] = new String[5];
+      int start_rc;
+      start_cmdarray[0] = d.XIToolsDir + "xi_phys_revoke";
+      start_cmdarray[1] = Integer.toString( domain_id );
+      start_cmdarray[2] = Short.toString( extent.getDisk() );
+      start_cmdarray[3] = Long.toString( extent.getOffset() );
+      start_cmdarray[4] = Long.toString( extent.getSize() );
+
+      if (Settings.TEST) {
+        output = reportCommand(start_cmdarray);
+      } else {
+        start_p = r.exec(start_cmdarray);
+        start_rc = start_p.waitFor();
+        if (start_rc != 0) {
+          throw CommandFailedException.XICommandFailed("Could not revoke physical access", start_cmdarray);
+        }
+        output = "Revoked physical access from domain " + domain_id;
+      }
+    } catch (CommandFailedException e) {
+      throw e;
+    } catch (Exception e) {
+      throw new CommandFailedException("Could not revoke physical access (" + e + ")", e);
+    }
+
+    return output;
+  }
+
+}
diff --git a/tools/control/src/org/xenoserver/control/Extent.java b/tools/control/src/org/xenoserver/control/Extent.java
new file mode 100644 (file)
index 0000000..e4ccff6
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Extent.java
+ * 03.03.26 aho creation
+ */
+
+package org.xenoserver.control;
+
+public class
+Extent
+{
+  short disk;
+  long offset;                                           /* offset into disk */
+  long size;                      /* size of this extent in 512 byte sectors */
+
+  public short
+  getDisk()
+  {
+    return disk;
+  }
+
+  public long
+  getOffset()
+  {
+    return offset;
+  }
+
+  public long
+  getSize()
+  {
+    return size;
+  }
+  
+  public int
+  getMajor()
+  {
+    return disk >> 8;
+  }
+  
+  public int
+  getMinor()
+  {
+    return disk & 0xFF;
+  }
+  
+  public int hashCode() {
+    final int PRIME = 1000003;
+    int result = 0;
+    result = PRIME * result + disk;
+    result = PRIME * result + (int) (offset >>> 32);
+    result = PRIME * result + (int) (offset & 0xFFFFFFFF);
+    result = PRIME * result + (int) (size >>> 32);
+    result = PRIME * result + (int) (size & 0xFFFFFFFF);
+
+    return result;
+  }
+
+  public boolean equals(Object oth) {
+    if (this == oth) {
+      return true;
+    }
+
+    if (oth == null) {
+      return false;
+    }
+
+    if (oth.getClass() != getClass()) {
+      return false;
+    }
+
+    Extent other = (Extent) oth;
+
+    if (this.disk != other.disk) {
+      return false;
+    }
+
+    if (this.offset != other.offset) {
+      return false;
+    }
+
+    if (this.size != other.size) {
+      return false;
+    }
+
+    return true;
+  }
+
+}
diff --git a/tools/control/src/org/xenoserver/control/Library.java b/tools/control/src/org/xenoserver/control/Library.java
new file mode 100644 (file)
index 0000000..b384bed
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Library.java
+ * 03.03.28 aho creation
+ */
+
+package org.xenoserver.control;
+
+public class
+Library
+{
+  /*
+   * convert a number to a fixed width string
+   */
+  public static String
+  format (long input, int width, int prefix)
+  {
+    String sss = Long.toString(input);
+    String space = "                                ";
+
+    if (width < sss.length())
+    {
+      width = sss.length();
+    }
+
+    if (prefix == 0)
+    {
+      return space.substring(0, width - sss.length()) + sss;
+    }
+    else
+    {
+      return sss + space.substring(0, width - sss.length());
+    }
+  }
+
+  /*
+   * convert a string to a fixed width string
+   */
+  public static String
+  format (String input, int width, int prefix)
+  {
+    String space = "                                ";
+
+    if (width < input.length())
+    {
+      width = input.length();
+    }
+
+    if (prefix == 0)
+    {
+      return space.substring(0, width - input.length()) + input;
+    }
+    else
+    {
+      return input + space.substring(0, width - input.length());
+    }
+  }
+
+  /*
+   * convert a number (string format) into 
+   * the corresponding integer value.
+   */
+  public static long
+  parse_size(String size)
+  {
+    String substring = size;
+    int    suffix = 1;
+    long   value = 0;
+
+    if (size == null)
+    {
+      return 0;
+    }
+
+    if ((substring = check(size, 'm')) != null)
+    {
+      suffix = 1024 * 1024;
+    }
+    else if ((substring = check(size, 'M')) != null)
+    {
+      suffix = 1024 * 1024;
+    }
+    else if ((substring = check(size, 'k')) != null)
+    {
+      suffix = 1024;
+    }
+    else if ((substring = check(size, 'K')) != null)
+    {
+      suffix = 1024;
+    }
+    else if ((substring = check(size, 'g')) != null)
+    {
+      suffix = 1024 * 1024 * 1024;
+    }
+    else if ((substring = check(size, 'G')) != null)
+    {
+      suffix = 1024 * 1024 * 1024;
+    }
+    else
+    {
+      substring = size;
+    }
+
+    try
+    {
+      value = Long.decode(substring).longValue() * suffix;
+    }
+    catch (NumberFormatException e)
+    {
+      value = 0;
+    }
+
+    return value;
+  }
+
+  public static String
+  check(String size, char suffix)
+  {
+    int index = size.indexOf(suffix);
+
+    if (index != -1)
+    {
+      return size.substring(0, index);
+    }
+    else
+    {
+      return null;
+    }
+  }
+}
diff --git a/tools/control/src/org/xenoserver/control/Mode.java b/tools/control/src/org/xenoserver/control/Mode.java
new file mode 100644 (file)
index 0000000..5f2ea4d
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Mode.java
+ * 03.03.27 aho creation
+ *
+ * until we have jdk1.5, we're left with this mess...
+ */
+
+package org.xenoserver.control;
+
+public class 
+Mode 
+{
+  private final String name;
+
+  private Mode(String name) { this.name = name; }
+
+  public String toString()  { return name; }
+
+  public static final Mode READ_ONLY  = new Mode("ro");
+  public static final Mode READ_WRITE = new Mode("rw");
+}
+
diff --git a/tools/control/src/org/xenoserver/control/Partition.java b/tools/control/src/org/xenoserver/control/Partition.java
new file mode 100644 (file)
index 0000000..03237c5
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * Partition.java
+ * 03.03.26 aho creation
+ */
+
+package org.xenoserver.control;
+
+import java.io.*;
+
+public class
+Partition
+{
+  int major;
+  int minor;
+  long blocks;
+  long start_sect;
+  long nr_sects;
+  String name;
+  boolean xeno;
+
+  Partition
+  duplicate ()
+  {
+    Partition p = new Partition();
+
+    p.major = major;
+    p.minor = minor;
+    p.blocks = blocks;
+    p.start_sect = start_sect;
+    p.nr_sects = nr_sects;
+    p.name = name;
+    p.xeno = xeno;
+
+    return p;
+  }
+
+  void
+  dump_xml(PrintWriter out)
+  {
+    out.println ("  <partition>\n" +
+                "    <major>" + major + "</major>\n" +
+                "    <minor>" + minor + "</minor>\n" +
+                "    <blocks>" + blocks + "</blocks>\n" +
+                "    <start_sect>" + start_sect + "</start_sect>\n" +
+                "    <nr_sects>" + nr_sects + "</nr_sects>\n" +
+                "    <name>" + name + "</name>\n" +
+                "  </partition>");
+  }
+
+  public int
+  getMajor()
+  {
+    return major;
+  }
+
+  public int
+  getMinor()
+  {
+    return minor;
+  }
+
+  public long
+  getBlocks()
+  {
+    return blocks;
+  }
+  
+  public long
+  getStartSect()
+  {
+    return start_sect;
+  }
+
+  public long
+  getNumSects()
+  {
+    return nr_sects;
+  }
+  
+  public String
+  getName()
+  {
+    return name;
+  }
+
+  public boolean
+  getIsXeno()
+  {
+    return xeno;
+  }
+
+  public int hashCode() {
+    final int PRIME = 1000003;
+    int result = 0;
+    result = PRIME * result + major;
+    result = PRIME * result + minor;
+    result = PRIME * result + (int) (blocks >>> 32);
+    result = PRIME * result + (int) (blocks & 0xFFFFFFFF);
+    result = PRIME * result + (int) (start_sect >>> 32);
+    result = PRIME * result + (int) (start_sect & 0xFFFFFFFF);
+    result = PRIME * result + (int) (nr_sects >>> 32);
+    result = PRIME * result + (int) (nr_sects & 0xFFFFFFFF);
+    if (name != null) {
+      result = PRIME * result + name.hashCode();
+    }
+
+    return result;
+  }
+
+  public boolean equals(Object oth) {
+    if (this == oth) {
+      return true;
+    }
+
+    if (oth == null) {
+      return false;
+    }
+
+    if (oth.getClass() != getClass()) {
+      return false;
+    }
+
+    Partition other = (Partition) oth;
+
+    if (this.major != other.major) {
+      return false;
+    }
+
+    if (this.minor != other.minor) {
+      return false;
+    }
+
+    if (this.blocks != other.blocks) {
+      return false;
+    }
+
+    if (this.start_sect != other.start_sect) {
+      return false;
+    }
+
+    if (this.nr_sects != other.nr_sects) {
+      return false;
+    }
+    if (this.name == null) {
+      if (other.name != null) {
+        return false;
+      }
+    } else {
+      if (!this.name.equals(other.name)) {
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+  /**
+   * @return An Extent covering this partiton.
+   */
+  public Extent toExtent()
+  {
+    Extent e = new Extent();
+    // Build 16-bit disk number.. high 8 bits are the major
+    int disknum = major << 8;
+    // Low 8 bits are the minor, but bottom 5 need to be cleared
+    // as they are the partition number, not the disk number
+    disknum |= ( minor & 0xE0 );
+    e.disk = (short) disknum;
+    e.offset = start_sect;
+    e.size = nr_sects;
+    return e;
+  }
+  
+  /**
+   * @param e Extent to compare this partition to.
+   * @return True if this partition covers the same disk area as the given extent.
+   */
+  public boolean matchesExtent( Extent e )
+  {
+    if ( e.getMajor() != major )
+      return false;
+    if ( e.getMinor() != (minor & 0xE0) )
+      return false;
+    if ( e.offset != start_sect )
+      return false;
+    if ( e.size != nr_sects )
+      return false;
+      
+    return true;
+  }
+}
diff --git a/tools/control/src/org/xenoserver/control/PartitionManager.java b/tools/control/src/org/xenoserver/control/PartitionManager.java
new file mode 100644 (file)
index 0000000..2609d45
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * PartitionManager.java
+ * 03.03.26 aho creation
+ */
+
+package org.xenoserver.control;
+
+import java.io.*;
+import java.util.Iterator;
+import java.util.Vector;
+import java.util.Enumeration;
+
+/**
+ * PartitionManager manages the partitions on the machine. It is a Singleton
+ * which automatically initialises itself on first class reference.
+ */
+public class
+PartitionManager
+{
+  static final String proc_template =
+    "major minor  #blocks  start_sect   nr_sects name";
+    
+  public static final PartitionManager it = new PartitionManager(Settings.PARTITIONS_FILE);
+    
+  Vector partition_map;
+
+  /*
+   * Initialize partition manager with source file.
+   * Normally we read from /proc/partitions, but we can
+   * specify an alternative file for debugging
+   */
+  private PartitionManager (String filename)
+  {
+    String str;
+    BufferedReader in;
+
+    partition_map = new Vector(100,10);
+
+    try
+    {
+      in = new BufferedReader(new FileReader(filename));
+
+      str = in.readLine();                                  /* skip headings */
+      if (str.length() < proc_template.length() ||
+         !str.substring(0, proc_template.length()).equals(proc_template))
+      {
+       System.err.println ("Error: Incorrect /proc/partitions.");
+       System.err.println ("       Is this Xeno?");
+       System.exit (1);
+      }
+
+      str = in.readLine();                                /* skip blank line */
+
+      str = in.readLine();
+      while (str != null)
+      {
+       Partition partition = new Partition();
+
+       partition.major = Integer.parseInt(str.substring(0,5).trim());
+       partition.minor = Integer.parseInt(str.substring(5,10).trim());
+       partition.blocks = Integer.parseInt(str.substring(10,21).trim());
+       partition.start_sect = Integer.parseInt(str.substring(21,32).trim());
+       partition.nr_sects = Integer.parseInt(str.substring(32,43).trim());
+       partition.name = str.substring(43).trim();
+       partition.xeno = false;
+
+       partition_map.add(partition);
+       str = in.readLine();
+      }
+    }
+    catch (IOException io)
+    {
+      System.err.println ("PartitionManager: error reading partition file [" 
+                         + filename + "]");
+      System.err.println (io);
+    }
+  }
+
+  public Partition
+  get_partition (String name)
+  {
+    Partition partition = null;
+    for (Enumeration e = partition_map.elements() ; e.hasMoreElements() ;) 
+    {
+      partition = (Partition) e.nextElement();
+      if (partition.name.equals(name))
+      {
+  return partition;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Finds the partition that matches the given extent, if any.
+   * @param extent The extent to compare to.
+   * @return The first matching partition, or null if none.
+   */
+  public Partition
+  get_partition (Extent extent)
+  {
+    Partition partition = null;
+    for (Enumeration e = partition_map.elements() ; e.hasMoreElements() ;) 
+    {
+      partition = (Partition) e.nextElement();
+      if (partition.matchesExtent(extent))
+      {
+  return partition;
+      }
+    }
+    return null;
+  }
+
+  Partition
+  get_partition (int index)
+  {
+    return (Partition) partition_map.get(index);
+  }
+
+  void
+  add_xeno_partition (Partition p)
+  {
+    for (Enumeration e = partition_map.elements() ; e.hasMoreElements() ;) 
+    {
+      Partition partition = (Partition) e.nextElement();
+      if (partition.equals(p))
+      {
+       partition.xeno = true;
+      }
+    }
+  }
+
+  /*
+   * dump the xeno partition list as xml
+   */
+  void
+  dump_xml (PrintWriter out)
+  {
+    int loop;
+
+    out.println("<partitions>");
+    for (Enumeration e = partition_map.elements() ; e.hasMoreElements() ;) 
+    {
+      Partition partition = (Partition) e.nextElement();
+      if (partition.xeno == true)
+      {
+       partition.dump_xml(out);
+      }
+    }
+
+    out.println("</partitions>");
+
+    return;
+  }
+
+  /**
+   * get the number of partitions 
+   */
+
+  int
+  getPartitionCount ()
+  {
+    return partition_map.size();
+  }
+
+  /**
+   * get the details about a particular partition
+   *
+   */
+  Partition
+  getPartition (int index)
+  {
+    Partition partition = (Partition) partition_map.get(index);
+    return partition;
+  }
+  /**
+   * Get an iterator over all the partitions.
+   * @return An iterator over Partition objects.
+   */
+  public Iterator iterator()
+  {
+    return partition_map.iterator();
+  }
+}
index 74203e618fa4d8c1a85c24f82bbb4dc3f58508a5..c6a1741ddaf35c0ee3ca41cfb1dbf77c6218080a 100644 (file)
@@ -16,7 +16,9 @@ public final class Settings
   public static final String LOCAL_GW = System.getProperty ("LOCAL_ROUTE");
   public static final boolean TEST = (System.getProperty ("TEST") != null);
   public static final String XI_HELPER = System.getProperty ("XI_HELPER", "xi_helper");
-
+  public static final String PARTITIONS_FILE = System.getProperty("PARTITIONS_FILE", "/proc/partitions");
+  public static final String STATE_INPUT_FILE = System.getProperty("STATE_INPUT_FILE", "/var/lib/xen/vdstate.xml");
+  public static final String STATE_OUTPUT_FILE = System.getProperty("STATE_OUTPUT_FILE", "/var/lib/xen/vdstate.xml");
 
   public static File getDefaultsFile() {
     StringTokenizer tok = new StringTokenizer (DEFAULTS_PATH, ":");
diff --git a/tools/control/src/org/xenoserver/control/XML.java b/tools/control/src/org/xenoserver/control/XML.java
new file mode 100644 (file)
index 0000000..d8331b9
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * XML.java
+ * 03.03.26 aho creation
+ */
+
+package org.xenoserver.control;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+public class
+XML
+{
+  static Document document = null;
+
+  /*
+   * dump partition manager and virtual disk manager state to filename
+   */
+
+  public static void
+  dump_state (PartitionManager pm,/* VirtualDiskManager vdm,*/ String filename)
+  {
+    PrintWriter out;
+
+    try
+    {
+      out = new PrintWriter(new BufferedWriter(new FileWriter(filename)));
+    }
+    catch (IOException e)
+    {
+      System.err.println ("XML.dump_state error [" + filename + "]");
+      System.err.println (e);
+      return;
+    }
+
+    out.println("<?xml version=\"1.0\"?>");
+    out.println("<vdmanager>");
+    pm.dump_xml(out);
+    //vdm.dump_xml(out);
+    out.println("</vdmanager>");
+
+    out.close();
+    return;
+  }
+
+  /*
+   * load partition manager and virtual disk manager state from filename
+   */
+  public static void
+  load_state (PartitionManager pm, /*VirtualDiskManager vdm,*/ String filename)
+  {
+    if (document == null)
+    {
+      load_file (filename);
+    }
+
+    XMLHelper.parse(pm, /*vdm,*/ document);
+  }
+
+  /*
+   * load XML from disk
+   */
+  static void
+  load_file (String filename)
+  {
+    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+    // factory.setNamespaceAware(true);
+    // factory.setValidating(true);
+
+    try
+    {
+      File file = new File(filename);
+
+      DocumentBuilder builder = factory.newDocumentBuilder();
+      document = builder.parse(file);
+    }
+    catch (SAXParseException spe)               /* error generated by parser */
+    {
+      System.err.println ("xml parser exception on line " + 
+                         spe.getLineNumber() + 
+                         " for uri " + spe.getSystemId());
+      System.err.println (spe.getMessage());
+
+      Exception x = spe;
+      if (spe.getException() != null)
+       x = spe.getException();
+      x.printStackTrace();
+      System.exit(1);
+    }
+    catch (SAXException sxe)
+    {
+      Exception e = sxe;
+      if (sxe.getException() != null)
+       e = sxe.getException();
+      e.printStackTrace();
+      System.exit(1);
+    }
+    catch (ParserConfigurationException pce)
+    {
+      pce.printStackTrace();
+    }
+    catch (FileNotFoundException fnfe)
+    {
+      System.err.println ("warning: state file not found [" +
+                         filename + "]");
+    }
+    catch (IOException ioe)
+    {
+      ioe.printStackTrace();
+    }
+    return;
+  }
+}
diff --git a/tools/control/src/org/xenoserver/control/XMLHelper.java b/tools/control/src/org/xenoserver/control/XMLHelper.java
new file mode 100644 (file)
index 0000000..5646e5c
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * XMLHelper.java
+ * 03.03.27 aho creation
+ */
+
+package org.xenoserver.control;
+
+import java.util.Date;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+public class
+XMLHelper
+{
+  static void
+  dump_document (Document document)
+  {
+    dump_element(document.getDocumentElement(), 0);
+  }
+
+  static void
+  dump_element (Element element, int indent)
+  {
+    NodeList nl = element.getChildNodes();
+
+    System.out.println ("<" + element.getTagName() + ">");
+    dump_nodelist(nl, indent + 1);
+    System.out.println("</" + element.getTagName() + ">");
+  }
+
+  static void
+  dump_nodelist (NodeList nl, int indent)
+  {
+    for (int loop = 0; loop < nl.getLength(); loop++)
+    {
+      Node node = nl.item(loop);
+      switch (node.getNodeType())
+      {
+       case Node.ELEMENT_NODE : 
+       {
+         dump_element((Element)node, indent);
+         break;
+       }
+       case Node.TEXT_NODE :
+       {
+         System.out.println("TEXT: " + node.getNodeValue());
+         break;
+       }
+       default :
+       {
+         System.out.println("NODE: " + node.getNodeType());
+       }
+      }
+    }
+  }
+
+  static Node 
+  get_subnode (String name, Node node) 
+  {
+    if (node.getNodeType() != Node.ELEMENT_NODE) 
+    {
+      System.err.println("Error: Search node not of element type");
+      return null;
+    }
+
+    if (!node.hasChildNodes()) return null;
+
+    NodeList list = node.getChildNodes();
+    for (int i=0; i < list.getLength(); i++) 
+    {
+      Node subnode = list.item(i);
+      if (subnode.getNodeType() == Node.ELEMENT_NODE) 
+      {
+       if (subnode.getNodeName() == name) return subnode;
+      }
+    }
+    return null;
+  }
+
+  static String 
+  get_text (Node node) 
+  {
+    StringBuffer result = new StringBuffer();
+    if (node==null || !node.hasChildNodes()) return "";
+
+    NodeList list = node.getChildNodes();
+    for (int i=0; i < list.getLength(); i++) 
+    {
+      Node subnode = list.item(i);
+      if (subnode.getNodeType() == Node.TEXT_NODE) 
+      {
+       result.append(subnode.getNodeValue());
+      }
+    }
+    return result.toString();
+  }
+
+  static void
+  parse (PartitionManager pm, /*VirtualDiskManager vdm,*/ Document document)
+  {
+    if (document == null) return;
+
+    /* parse partitions */
+    parse_partitions(pm, document.getElementsByTagName("partition"));
+/*
+    / parse virtual disks /
+    NodeList list = document.getElementsByTagName("virtual_disk");
+    for (int i = 0; i < list.getLength(); i++)
+    {
+      Node subnode = list.item(i);
+      String parent = subnode.getParentNode().getNodeName();
+      VirtualDisk vd =  parse_virtual_disk(subnode);
+
+      if (parent.equals("free"))
+      {
+       vdm.add_free(vd);
+      }
+      else if (parent.equals("virtual_disks"))
+      {
+       vdm.add_virtual_disk(vd);
+      }
+      else
+      {
+       System.out.println ("XML parse error: unknown parent for virtual_disk "
+                           + "[" + parent + "]");
+      }
+    }
+
+    / parse virtual block devices /
+    parse_virtual_block_devices(vdm, document.getElementsByTagName("virtual_block_device"));
+*/
+    return;
+  }
+
+ /* static VirtualDisk
+  parse_virtual_disk(Node node)
+  {
+    VirtualDisk vd;
+    Date date = new Date();
+    NodeList list;
+
+    date.setTime(Long.parseLong(XMLHelper.get_text(XMLHelper.get_subnode("expiry", node))));
+    vd = new VirtualDisk(XMLHelper.get_text(XMLHelper.get_subnode("name", node)),
+                        date,
+                        XMLHelper.get_text(XMLHelper.get_subnode("key", node)));
+
+    list = XMLHelper.get_subnode("extents", node).getChildNodes();
+    for (int i = 0; i < list.getLength(); i++)
+    {
+      Node enode = list.item(i);
+
+      if (enode.getNodeType() == Node.ELEMENT_NODE &&
+         enode.getNodeName().equals("extent"))
+      {
+       Extent extent = new Extent();
+
+       extent.disk = Integer.parseInt(XMLHelper.get_text(XMLHelper.get_subnode("disk", enode)));
+       extent.size = Long.parseLong(XMLHelper.get_text(XMLHelper.get_subnode("size", enode)));
+       extent.offset = Long.parseLong(XMLHelper.get_text(XMLHelper.get_subnode("offset", enode)));
+       vd.add_extent(extent);
+      }
+    }
+
+    return vd;
+  }*/
+
+  static void
+  parse_partitions (PartitionManager pm, NodeList nl)
+  {
+    Partition partition;
+
+    for (int loop = 0; loop < nl.getLength(); loop++)
+    {
+      Node node = nl.item(loop);
+
+      partition = new Partition();
+      partition.major = Integer.parseInt(XMLHelper.get_text(XMLHelper.get_subnode("major", node)));
+      partition.minor = Integer.parseInt(XMLHelper.get_text(XMLHelper.get_subnode("minor", node)));
+      partition.blocks = Integer.parseInt(XMLHelper.get_text(XMLHelper.get_subnode("blocks", node)));
+      partition.start_sect = Integer.parseInt(XMLHelper.get_text(XMLHelper.get_subnode("start_sect", node)));
+      partition.nr_sects = Integer.parseInt(XMLHelper.get_text(XMLHelper.get_subnode("nr_sects", node)));
+      partition.name = XMLHelper.get_text(XMLHelper.get_subnode("name", node));
+
+      pm.add_xeno_partition(partition);
+    }
+  }
+/*
+  static void
+  parse_virtual_block_devices (VirtualDiskManager vdm, NodeList nl)
+  {
+    VirtualBlockDevice vbd;
+
+    for (int loop = 0; loop < nl.getLength(); loop++)
+    {
+      Node node = nl.item(loop);
+
+      vdm.create_virtual_block_device(XMLHelper.get_text(XMLHelper.get_subnode("key", node)),
+                                     Integer.parseInt(XMLHelper.get_text(XMLHelper.get_subnode("domain", node))),
+                                     Integer.parseInt(XMLHelper.get_text(XMLHelper.get_subnode("vbdnum", node))),
+                                     XMLHelper.get_text(XMLHelper.get_subnode("mode", node)));
+    }
+  }*/
+}